#ifndef __JIGSAW_PUZZLE_H__
#define __JIGSAW_PUZZLE_H__

// There are three types of edges:
// 1. flat, inner, outer
// 2. Each piece has four edges

enum TYPE {
    FLAT = 0,
    INNER = 1,
    OUTER = 2
};

// Edge definition
struct Edge {
    TYPE type;
    size_t len;
};

// 
class Piece {
public:
    Piece(Edge *edges);
    ~Piece();

    Edge *getEdges();

private:

    Edge edge_[4];
};

// Jigsaw puzzle game
class JigsawPuzzle {
public:
    JigsawPuzzle(int height, int width);
    ~JigsawPuzzle();

    void setPieces(Piece *pieces);
    void solve();

private:
    sortPieces();

private:
    Edge *exposed_edges_;
    Piece *pieces_;
    int height_;
    int width_;
    int piece_num_;
    int *inner_list_;
    int *outer_list_;
    int *flat_list_;
};


JigsawPuzzle::JigsawPuzzle(int height, int width) {
    height_ = height;
    width_ = width;
    piece_num_ = height * width;

    pieces_ = new Piece[piece_num_];
    inner_list_ = new int[piece_num_ * 4];
    outer_list_ = new int[piece_num_ * 4];
    flat_list_ = new int[2 * (height_ + width_)];
}

JigsawPuzzle::sortPiece() {
    
}

JigsawPuzzle::solve() {
    // 1. Find the four corner piece, each of which has two 
    //    flat edged.
    // 2. Construct the list of flat edges, and sort them
    // 3. Construct the list of outter edges and sort them
    // 4. Construct the list of inner edges and sort them.

    // 5. Add the other six edges of the four corner pieces
    //    to the exposed list.

    // 6. For each exposed edge, corresponding to the type
    //    and the len, find the matched pieces, then remove
    //    the piece from the corresponding list, add the edges
    //    of the other two sides to the exposed.
    // 7. Repeat step 6 until all pieces are arranged.
}

#endif

